 /*******************************************************************************
  * Copyright (c) 2002, 2007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
  * Contributors:
  * IBM Corporation - initial API and implementation
  *******************************************************************************/
 package org.eclipse.ui.internal.cheatsheets.dialogs;

 import java.io.File ;
 import java.net.MalformedURLException ;
 import java.net.URL ;
 import java.util.ArrayList ;
 import java.util.List ;

 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Path;
 import org.eclipse.core.runtime.Status;
 import org.eclipse.jface.dialogs.Dialog;
 import org.eclipse.jface.dialogs.IDialogConstants;
 import org.eclipse.jface.dialogs.IDialogSettings;
 import org.eclipse.jface.dialogs.TrayDialog;
 import org.eclipse.jface.viewers.DoubleClickEvent;
 import org.eclipse.jface.viewers.IContentProvider;
 import org.eclipse.jface.viewers.IDoubleClickListener;
 import org.eclipse.jface.viewers.ISelection;
 import org.eclipse.jface.viewers.ISelectionChangedListener;
 import org.eclipse.jface.viewers.IStructuredSelection;
 import org.eclipse.jface.viewers.LabelProvider;
 import org.eclipse.jface.viewers.SelectionChangedEvent;
 import org.eclipse.jface.viewers.StructuredSelection;
 import org.eclipse.jface.viewers.TreeViewer;
 import org.eclipse.jface.viewers.Viewer;
 import org.eclipse.jface.viewers.ViewerFilter;
 import org.eclipse.osgi.util.NLS;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.custom.SashForm;
 import org.eclipse.swt.events.ModifyEvent;
 import org.eclipse.swt.events.ModifyListener;
 import org.eclipse.swt.events.SelectionAdapter;
 import org.eclipse.swt.events.SelectionEvent;
 import org.eclipse.swt.events.SelectionListener;
 import org.eclipse.swt.graphics.Image;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Button;
 import org.eclipse.swt.widgets.Combo;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.FileDialog;
 import org.eclipse.swt.widgets.Label;
 import org.eclipse.swt.widgets.Shell;
 import org.eclipse.swt.widgets.Text;
 import org.eclipse.ui.ISharedImages;
 import org.eclipse.ui.PlatformUI;
 import org.eclipse.ui.activities.ITriggerPoint;
 import org.eclipse.ui.activities.WorkbenchActivityHelper;
 import org.eclipse.ui.cheatsheets.OpenCheatSheetAction;
 import org.eclipse.ui.internal.cheatsheets.CheatSheetPlugin;
 import org.eclipse.ui.internal.cheatsheets.ICheatSheetResource;
 import org.eclipse.ui.internal.cheatsheets.Messages;
 import org.eclipse.ui.internal.cheatsheets.data.ParserStatusUtility;
 import org.eclipse.ui.internal.cheatsheets.registry.CheatSheetCollectionElement;
 import org.eclipse.ui.internal.cheatsheets.registry.CheatSheetCollectionSorter;
 import org.eclipse.ui.internal.cheatsheets.registry.CheatSheetElement;
 import org.eclipse.ui.internal.cheatsheets.state.DefaultStateManager;
 import org.eclipse.ui.internal.cheatsheets.views.CheatSheetView;
 import org.eclipse.ui.internal.cheatsheets.views.ViewUtilities;
 import org.eclipse.ui.model.BaseWorkbenchContentProvider;
 import org.eclipse.ui.model.WorkbenchAdapter;

 /**
  * Dialog to allow the user to select a cheat sheet from a list.
  */
 public class CheatSheetCategoryBasedSelectionDialog extends TrayDialog //extends SelectionDialog
 implements ISelectionChangedListener {
     private static final String CHEAT_SHEET_SELECTION_HELP_ID = "org.eclipse.ui.cheatsheets.cheatSheetSelection"; //$NON-NLS-1$

     private IDialogSettings settings;

     private CheatSheetCollectionElement cheatsheetCategories;

     private CheatSheetElement currentSelection;

     private TreeViewer treeViewer;

     private Text desc;

     private Button showAllButton;
     
     private Button selectRegisteredRadio;
     
     private Button selectFileRadio;
     
     private Button selectUrlRadio;

     private Combo selectFileCombo;
     
     private Combo selectUrlCombo;

     private ActivityViewerFilter activityViewerFilter = new ActivityViewerFilter();

     private boolean okButtonState;

     // id constants

     private static final String DIALOG_SETTINGS_SECTION = "CheatSheetCategoryBasedSelectionDialog"; //$NON-NLS-1$

     private final static String STORE_EXPANDED_CATEGORIES_ID = "CheatSheetCategoryBasedSelectionDialog.STORE_EXPANDED_CATEGORIES_ID"; //$NON-NLS-1$

     private final static String STORE_SELECTED_CHEATSHEET_ID = "CheatSheetCategoryBasedSelectionDialog.STORE_SELECTED_CHEATSHEET_ID"; //$NON-NLS-1$

     private final static String STORE_RADIO_SETTING = "CheatSheetCategoryBasedSelectionDialog.STORE_RADIO_SELECTION"; //$NON-NLS-1$

     private final static String STORE_CHEATSHEET_FILENAME = "CheatSheetCategoryBasedSelectionDialog.STORE_CHEATSHEET_FILENAME"; //$NON-NLS-1$

     private final static String STORE_CHEATSHEET_URL = "CheatSheetCategoryBasedSelectionDialog.STORE_CHEATSHEET_URL"; //$NON-NLS-1$

     private final static String STORE_URL_MRU = "CheatSheetCategoryBasedSelectionDialog.STORE_URL_MRU"; //$NON-NLS-1$
 private final static String STORE_FILE_MRU = "CheatSheetCategoryBasedSelectionDialog.STORE_FILE_MRU"; //$NON-NLS-1$

     private static final int MOST_RECENT_LENGTH = 3;
     private static final int RADIO_REGISTERED = 1;
     private static final int RADIO_FILE = 2;
     private static final int RADIO_URL = 3;
     
     private Button browseFileButton;

     private String title;

     private IStatus status = Status.OK_STATUS;
     
     
     List mostRecentFiles = new ArrayList ();
     List mostRecentUrls = new ArrayList ();

     private static class ActivityViewerFilter extends ViewerFilter {
         private boolean hasEncounteredFilteredItem = false;

         /*
          * (non-Javadoc)
          *
          * @see org.eclipse.jface.viewers.ViewerFilter#select(org.eclipse.jface.viewers.Viewer,
          * java.lang.Object, java.lang.Object)
          */
         public boolean select(Viewer viewer, Object parentElement,
                 Object element) {
             if (WorkbenchActivityHelper.filterItem(element)) {
                 setHasEncounteredFilteredItem(true);
                 return false;
             }
             return true;
         }

         /**
          * @return returns whether the filter has filtered an item
          */
         public boolean getHasEncounteredFilteredItem() {
             return hasEncounteredFilteredItem;
         }

         /**
          * @param sets
          * whether the filter has filtered an item
          */
         public void setHasEncounteredFilteredItem(
                 boolean hasEncounteredFilteredItem) {
             this.hasEncounteredFilteredItem = hasEncounteredFilteredItem;
         }
     }

     private class CheatsheetLabelProvider extends LabelProvider {
         public String getText(Object obj) {
             if (obj instanceof WorkbenchAdapter) {
                 return ((WorkbenchAdapter) obj).getLabel(null);
             }
             return super.getText(obj);
         }

         public Image getImage(Object obj) {
             if (obj instanceof CheatSheetElement) {
                 CheatSheetElement element = (CheatSheetElement)obj;
                 if (element.isComposite()) {
                     return CheatSheetPlugin.getPlugin().getImageRegistry().get(
                             ICheatSheetResource.COMPOSITE_OBJ);
                 }
                 return CheatSheetPlugin.getPlugin().getImageRegistry().get(
                         ICheatSheetResource.CHEATSHEET_OBJ);
             }
             return PlatformUI.getWorkbench().getSharedImages().getImage(
                     ISharedImages.IMG_OBJ_FOLDER);
         }
     }

     /**
      * Creates an instance of this dialog to display the a list of cheat sheets.
      *
      * @param shell
      * the parent shell
      */
     public CheatSheetCategoryBasedSelectionDialog(Shell shell,
             CheatSheetCollectionElement cheatsheetCategories) {
         super(shell);

         this.cheatsheetCategories = cheatsheetCategories;

         this.title = Messages.CHEAT_SHEET_SELECTION_DIALOG_TITLE;

         setShellStyle(getShellStyle() | SWT.RESIZE);
     }

     /*
      * (non-Javadoc) Method declared on Window.
      */
     protected void configureShell(Shell newShell) {
         super.configureShell(newShell);
         if (title != null) {
             newShell.setText(title);
         }
         newShell.setImage(CheatSheetPlugin.getPlugin().getImage(ICheatSheetResource.CHEATSHEET_VIEW));
     }

     /*
      * (non-Javadoc) Method declared on Dialog.
      */
     protected void createButtonsForButtonBar(Composite parent) {
         super.createButtonsForButtonBar(parent);

         enableOKButton(okButtonState);
     }

     /*
      * (non-Javadoc) Method declared on Dialog.
      */
     protected Control createDialogArea(Composite parent) {
         initializeDialogUnits(parent);
         
         IDialogSettings workbenchSettings = CheatSheetPlugin.getPlugin()
                 .getDialogSettings();
         IDialogSettings dialogSettings = workbenchSettings
                 .getSection(DIALOG_SETTINGS_SECTION);
         if (dialogSettings == null)
             dialogSettings = workbenchSettings
                     .addNewSection(DIALOG_SETTINGS_SECTION);

         setDialogSettings(dialogSettings);

         // top level group
 Composite outerContainer = (Composite) super.createDialogArea(parent);

         PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, CHEAT_SHEET_SELECTION_HELP_ID);
         GridLayout gridLayout = new GridLayout();
         gridLayout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
         gridLayout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
         gridLayout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
         gridLayout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
         outerContainer.setLayout(gridLayout);
         outerContainer.setLayoutData(new GridData(GridData.FILL_BOTH));

         // Create label
 createMessageArea(outerContainer);
         
         // Create radio button
 selectRegisteredRadio = new Button(outerContainer, SWT.RADIO);
         selectRegisteredRadio.setText(Messages.SELECTION_DIALOG_OPEN_REGISTERED);
         
         SashForm sform = new SashForm(outerContainer, SWT.VERTICAL);
         GridData data = new GridData(GridData.FILL_BOTH);
         data.heightHint = 300;
         sform.setLayoutData(data);
         
         // category tree pane
 treeViewer = new TreeViewer(sform, SWT.SINGLE | SWT.H_SCROLL
                 | SWT.V_SCROLL | SWT.BORDER);
         treeViewer.getTree().setLayoutData(data);
         treeViewer.setContentProvider(getCheatSheetProvider());
         treeViewer.setLabelProvider(new CheatsheetLabelProvider());
         treeViewer.setComparator(CheatSheetCollectionSorter.INSTANCE);
         treeViewer.addFilter(activityViewerFilter);
         treeViewer.addSelectionChangedListener(this);
         treeViewer.setInput(cheatsheetCategories);

         desc = new Text(sform, SWT.MULTI | SWT.WRAP);
         desc.setEditable(false);

         sform.setWeights(new int[] {10, 2});
         
         if (activityViewerFilter.getHasEncounteredFilteredItem())
             createShowAllButton(outerContainer);

         // Add double-click listener
 treeViewer.addDoubleClickListener(new IDoubleClickListener() {
             public void doubleClick(DoubleClickEvent event) {
                 IStructuredSelection selection = (IStructuredSelection)event.getSelection();
                 Object obj = selection.getFirstElement();
                 if (obj instanceof CheatSheetCollectionElement) {
                     boolean state = treeViewer.getExpandedState(obj);
                     treeViewer.setExpandedState(obj, !state);
                 }
                 else {
                     okPressed();
                 }
             }
         });
         
         // Create radio button for select from file
 selectFileRadio = new Button(outerContainer, SWT.RADIO);
         selectFileRadio.setText(Messages.SELECTION_DIALOG_OPEN_FROM_FILE);
         
         Composite selectFileComposite = new Composite(outerContainer, SWT.NULL);
         GridLayout selectFileLayout = new GridLayout();
         selectFileLayout.marginWidth = 0;
         selectFileLayout.marginHeight = 0;
         selectFileLayout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
         selectFileLayout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
         selectFileLayout.numColumns = 2;
         selectFileComposite.setLayout(selectFileLayout);
         GridData sfCompositeData = new GridData(GridData.FILL_HORIZONTAL);
         sfCompositeData.widthHint = 300;
         selectFileComposite.setLayoutData(sfCompositeData);
         selectFileCombo = new Combo(selectFileComposite, SWT.BORDER);
         GridData sfTextData = new GridData(GridData.FILL_HORIZONTAL);
         selectFileCombo.setLayoutData(sfTextData);
         browseFileButton = new Button(selectFileComposite, SWT.NULL);
         browseFileButton.setText(Messages.SELECTION_DIALOG_FILEPICKER_BROWSE);
         setButtonLayoutData(browseFileButton);
         
         // Create radio button for select from URL
 selectUrlRadio = new Button(outerContainer, SWT.RADIO);
         selectUrlRadio.setText(Messages.SELECTION_DIALOG_OPEN_FROM_URL);
         selectUrlCombo = new Combo(outerContainer, SWT.BORDER);
         GridData suTextData = new GridData(GridData.FILL_HORIZONTAL);
         selectUrlCombo.setLayoutData(suTextData);
         
         restoreWidgetValues();
         restoreFileSettings();

         if (!treeViewer.getSelection().isEmpty())
             // we only set focus if a selection was restored
 treeViewer.getTree().setFocus();

         Dialog.applyDialogFont(outerContainer);
         selectFileCombo.addModifyListener(new FileAndUrlListener());
         browseFileButton.addSelectionListener(new BrowseListener());
         selectRegisteredRadio.addSelectionListener(new RadioSelectionListener());
         selectUrlRadio.addSelectionListener(new RadioSelectionListener());
         selectUrlCombo.addModifyListener(new FileAndUrlListener());
         checkRadioButtons();
         return outerContainer;
     }
     
     private class RadioSelectionListener implements SelectionListener {

         public void widgetSelected(SelectionEvent e) {
             checkRadioButtons();
         }

         public void widgetDefaultSelected(SelectionEvent e) {
             // do nothing
 }
     }
     
     private class BrowseListener implements SelectionListener {

         public void widgetSelected(SelectionEvent e) {
             // Launch a file dialog to select a cheatsheet file
 FileDialog fileDlg = new FileDialog(getShell());
             fileDlg.setFilterExtensions(new String []{"*.xml"}); //$NON-NLS-1$
 fileDlg.setText(Messages.SELECTION_DIALOG_FILEPICKER_TITLE);
             fileDlg.open();
             String filename = fileDlg.getFileName();
             if (filename != null) {
                 IPath folderPath = new Path(fileDlg.getFilterPath());
                 IPath filePath = folderPath.append(filename);
                 selectFileCombo.setText(filePath.toOSString());
                 checkRadioButtons();
             }
         }

         public void widgetDefaultSelected(SelectionEvent e) {
             // do nothing
 }
     }
     
     private class FileAndUrlListener implements ModifyListener {

         public void modifyText(ModifyEvent e) {
             setOkButton();
         }
     }

     /*
      * Check the state of the Radio buttons and disable those parts of the UI that don't apply
      */
     private void checkRadioButtons() {
         selectFileCombo.setEnabled(selectFileRadio.getSelection());
         browseFileButton.setEnabled(selectFileRadio.getSelection());
         if (showAllButton != null) {
             showAllButton.setEnabled(selectRegisteredRadio.getSelection());
         }
         treeViewer.getTree().setEnabled(selectRegisteredRadio.getSelection());
         selectUrlCombo.setEnabled(selectUrlRadio.getSelection());
         setOkButton();
     }

     /**
      * Create a show all button in the parent.
      *
      * @param parent
      * the parent <code>Composite</code>.
      */
     private void createShowAllButton(Composite parent) {
         showAllButton = new Button(parent, SWT.CHECK);
         showAllButton
                 .setText(Messages.CheatSheetCategoryBasedSelectionDialog_showAll);
         showAllButton.addSelectionListener(new SelectionAdapter() {

             /*
              * (non-Javadoc)
              *
              * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
              */
             public void widgetSelected(SelectionEvent e) {
                 if (showAllButton.getSelection()) {
                     treeViewer.resetFilters();
                 } else {
                     treeViewer.addFilter(activityViewerFilter);
                 }
             }
         });
     }

     /**
      * Method enableOKButton enables/diables the OK button for the dialog and
      * saves the state, allowing the enabling/disabling to occur even if the
      * button has not been created yet.
      *
      * @param value
      */
     private void enableOKButton(boolean value) {
         Button button = getButton(IDialogConstants.OK_ID);

         okButtonState = value;
         if (button != null) {
             button.setEnabled(value);
         }
     }

     /**
      * Expands the cheatsheet categories in this page's category viewer that
      * were expanded last time this page was used. If a category that was
      * previously expanded no longer exists then it is ignored.
      */
     protected CheatSheetCollectionElement expandPreviouslyExpandedCategories() {
         String [] expandedCategoryPaths = settings
                 .getArray(STORE_EXPANDED_CATEGORIES_ID);
         List categoriesToExpand = new ArrayList (expandedCategoryPaths.length);

         for (int i = 0; i < expandedCategoryPaths.length; i++) {
             CheatSheetCollectionElement category = cheatsheetCategories
                     .findChildCollection(new Path(expandedCategoryPaths[i]));
             if (category != null) // ie.- it still exists
 categoriesToExpand.add(category);
         }

         if (!categoriesToExpand.isEmpty())
             treeViewer.setExpandedElements(categoriesToExpand.toArray());
         return categoriesToExpand.isEmpty() ? null
                 : (CheatSheetCollectionElement) categoriesToExpand
                         .get(categoriesToExpand.size() - 1);
     }

     /**
      * Returns the content provider for this page.
      */
     protected IContentProvider getCheatSheetProvider() {
         // want to get the cheatsheets of the collection element
 return new BaseWorkbenchContentProvider() {
             public Object [] getChildren(Object o) {
                 Object [] cheatsheets;
                 if (o instanceof CheatSheetCollectionElement) {
                     cheatsheets = ((CheatSheetCollectionElement) o)
                             .getCheatSheets();
                 } else {
                     cheatsheets = new Object [0];
                 }
                 Object [] subCategories = super.getChildren(o);
                 if (cheatsheets.length == 0) {
                     return subCategories;
                 } else if (subCategories.length == 0) {
                     return cheatsheets;
                 } else {
                     Object [] result = new Object [cheatsheets.length + subCategories.length];
                     System.arraycopy(subCategories, 0, result, 0, subCategories.length);
                     System.arraycopy(cheatsheets, 0, result, subCategories.length, cheatsheets.length);
                     return result;
                 }
             }
         };
     }

     /**
      * Returns the single selected object contained in the passed
      * selectionEvent, or <code>null</code> if the selectionEvent contains
      * either 0 or 2+ selected objects.
      */
     protected Object getSingleSelection(ISelection selection) {
         IStructuredSelection ssel = (IStructuredSelection) selection;
         return ssel.size() == 1 ? ssel.getFirstElement() : null;
     }

     /**
      * The user selected either new cheatsheet category(s) or cheatsheet
      * element(s). Proceed accordingly.
      *
      * @param newSelection
      * ISelection
      */
     public void selectionChanged(SelectionChangedEvent selectionEvent) {
         Object obj = getSingleSelection(selectionEvent.getSelection());
         if (obj instanceof CheatSheetCollectionElement) {
             currentSelection = null;
         } else {
             currentSelection = (CheatSheetElement) obj;
         }

         if (currentSelection != null) {
             desc.setText(currentSelection.getDescription());
         } else {
             desc.setText(""); //$NON-NLS-1$
 }
         setOkButton();
     }
     
     private void setOkButton() {
         if (selectRegisteredRadio.getSelection()) {
             enableOKButton(currentSelection != null);
         } else if (selectFileRadio.getSelection() ){
             enableOKButton(selectFileCombo.getText().length() > 0);
         } else {
             enableOKButton(selectUrlCombo.getText().length() > 0);
         }
     }

     /*
      * (non-Javadoc) Method declared on Dialog.
      */
     protected void okPressed() {
         /*
          * Prevent the cheat sheet from opening inside this dialog's tray
          * because it is about to close.
          */
         getShell().setVisible(false);
         
         if (selectFileRadio.getSelection()) {
             setResultFromFile();
         } else if (selectRegisteredRadio.getSelection() ){
             setResultFromTree();
         } else {
             setResultFromUrl();
         }

         // save our selection state
 saveWidgetValues();

         super.okPressed();
     }

     private void setResultFromTree() {
         if (currentSelection != null) {
             ITriggerPoint triggerPoint = PlatformUI.getWorkbench()
                     .getActivitySupport().getTriggerPointManager()
                     .getTriggerPoint(ICheatSheetResource.TRIGGER_POINT_ID);
             if (WorkbenchActivityHelper.allowUseOf(triggerPoint,
                     currentSelection)) {
                 new OpenCheatSheetAction(currentSelection.getID()).run();
             }
         }
     }

     private void setResultFromFile() {
         // Use the filename without extension as the id of this cheatsheet
 IPath filePath = new Path(selectFileCombo.getText());
         String id = filePath.lastSegment();
         int extensionIndex = id.indexOf('.');
         if (extensionIndex > 0) {
             id = id.substring(0, extensionIndex);
         }
         // Use the id as the name
 URL url = null;
         boolean opened = false;
         
         try {
             File contentFile = new File (selectFileCombo.getText());
             url = contentFile.toURL();
             new OpenCheatSheetAction(id, id ,url).run();
             opened = true;
         } catch (MalformedURLException e) {
             opened = false;
         }
         if (!opened) {
             String message = NLS.bind(Messages.ERROR_OPENING_FILE, (new Object [] {selectFileCombo.getText()}));
             status = new Status(IStatus.ERROR, ICheatSheetResource.CHEAT_SHEET_PLUGIN_ID, ParserStatusUtility.PARSER_ERROR, message, null);
             CheatSheetView view = ViewUtilities.showCheatSheetView();
             view.getCheatSheetViewer().showError(message);
         }
     }
     
     private void setResultFromUrl() {
         // Use the filename without extension as the id of this cheatsheet
 IPath filePath = new Path(selectUrlCombo.getText());
         String id = filePath.lastSegment();
         int extensionIndex = id.indexOf('.');
         if (extensionIndex > 0) {
             id = id.substring(0, extensionIndex);
         }
         // Use the id as the name
 URL url = null;
         boolean opened = false;
         CheatSheetView view = ViewUtilities.showCheatSheetView();
         if (view == null) {
             return;
         }
         try {
             url = new URL (selectUrlCombo.getText());
             view.getCheatSheetViewer().setInput(id, id, url, new DefaultStateManager(), true);
             opened = true;
         } catch (MalformedURLException e) {
             opened = false;
         }
         if (!opened) {
             String message = NLS.bind(Messages.ERROR_OPENING_FILE, (new Object [] {selectUrlCombo.getText()}));
             status = new Status(IStatus.ERROR, ICheatSheetResource.CHEAT_SHEET_PLUGIN_ID, ParserStatusUtility.PARSER_ERROR, message, null);
             view.getCheatSheetViewer().showError(message);
         }
     }

     /**
      * Set's widgets to the values that they held last time this page was
      * opened
      */
     protected void restoreWidgetValues() {
         String [] expandedCategoryPaths = settings
                 .getArray(STORE_EXPANDED_CATEGORIES_ID);
         if (expandedCategoryPaths == null)
             return; // no stored values

         CheatSheetCollectionElement category = expandPreviouslyExpandedCategories();
         if (category != null)
             selectPreviouslySelectedCheatSheet(category);
     }
     
     /**
      * Restores the state of the radio button and file name fields
      */
     private void restoreFileSettings() {
         int radioSetting = RADIO_REGISTERED;
         try {
              radioSetting = settings.getInt(STORE_RADIO_SETTING);
         }
         catch(NumberFormatException n) {
         }
         selectFileRadio.setSelection(radioSetting == RADIO_FILE);
         selectRegisteredRadio.setSelection(radioSetting == RADIO_REGISTERED);
         selectUrlRadio.setSelection(radioSetting == RADIO_URL);
         String fileName = settings.get(STORE_CHEATSHEET_FILENAME);
         if (fileName != null) {
             selectFileCombo.setText(fileName);
         }
         String url = settings.get(STORE_CHEATSHEET_URL);
         if (url != null) {
             selectUrlCombo.setText(url);
         }
         loadMRU(mostRecentUrls, STORE_URL_MRU, selectUrlCombo);
         loadMRU(mostRecentFiles, STORE_FILE_MRU, selectFileCombo);
     }

     private void loadMRU(List mostRecentList, String key, Combo combo) {
         for (int i = 0; i < MOST_RECENT_LENGTH; i++) {
             String name = settings.get(key + i);
             if (name != null) {
                 mostRecentList.add(name);
                 combo.add(name);
             }
         }
     }
     
     private void saveMRU(List mostRecentList, String key, String selection) {
         if (selection.length() > 0 && !mostRecentList.contains(selection)) {
             mostRecentList.add(0, selection);
         }
         for (int i = 0; i < MOST_RECENT_LENGTH & i < mostRecentList.size(); i++) {
             String name = (String )mostRecentList.get(i);
             if (name.length() > 0) {
                 settings.put(key + i, name);
             }
         }
     }

     /**
      * Store the current values of self's widgets so that they can be restored
      * in the next instance of self
      *
      */
     public void saveWidgetValues() {
         storeExpandedCategories();
         storeSelectedCheatSheet();
         storeFileSettings();
     }

     /**
      * Selects the cheatsheet category and cheatsheet in this page that were
      * selected last time this page was used. If a category or cheatsheet that
      * was previously selected no longer exists then it is ignored.
      */
     protected void selectPreviouslySelectedCheatSheet(
             CheatSheetCollectionElement category) {
         String cheatsheetId = settings.get(STORE_SELECTED_CHEATSHEET_ID);
         if (cheatsheetId == null)
             return;
         CheatSheetElement cheatsheet = category.findCheatSheet(cheatsheetId,
                 false);
         if (cheatsheet == null)
             return; // cheatsheet no longer exists, or has moved

         treeViewer.setSelection(new StructuredSelection(cheatsheet));
     }

     /**
      * Set the dialog store to use for widget value storage and retrieval
      *
      * @param settings
      * IDialogSettings
      */
     public void setDialogSettings(IDialogSettings settings) {
         this.settings = settings;
     }

     /**
      * Stores the collection of currently-expanded categories in this page's
      * dialog store, in order to recreate this page's state in the next instance
      * of this page.
      */
     protected void storeExpandedCategories() {
         Object [] expandedElements = treeViewer.getExpandedElements();
         String [] expandedElementPaths = new String [expandedElements.length];
         for (int i = 0; i < expandedElements.length; ++i) {
             expandedElementPaths[i] = ((CheatSheetCollectionElement) expandedElements[i])
                     .getPath().toString();
         }
         settings.put(STORE_EXPANDED_CATEGORIES_ID, expandedElementPaths);
     }

     /**
      * Stores the currently-selected category and cheatsheet in this page's
      * dialog store, in order to recreate this page's state in the next instance
      * of this page.
      */
     protected void storeSelectedCheatSheet() {
         CheatSheetElement element = null;

         Object el = getSingleSelection(treeViewer.getSelection());
         if (el == null)
             return;

         if (el instanceof CheatSheetElement) {
             element = (CheatSheetElement) el;
         } else
             return;

         settings.put(STORE_SELECTED_CHEATSHEET_ID, element.getID());
     }
     
     /**
      * Stores the state of the radio button and file name fields
      */
     private void storeFileSettings() {
         int radioSetting = 0;
         if (selectRegisteredRadio.getSelection()) {
             radioSetting = 1;
         }
         if (selectFileRadio.getSelection()) {
             radioSetting = 2;
         }
         if (selectUrlRadio.getSelection()) {
             radioSetting = 3;
         }
         settings.put(STORE_RADIO_SETTING, radioSetting);
         settings.put(STORE_CHEATSHEET_FILENAME, selectFileCombo.getText());
         settings.put(STORE_CHEATSHEET_URL, selectUrlCombo.getText());

         saveMRU(mostRecentUrls, STORE_URL_MRU, selectUrlCombo.getText());
         saveMRU(mostRecentFiles, STORE_FILE_MRU, selectFileCombo.getText());
     }
     
     /* (non-Javadoc)
      * @see org.eclipse.jface.window.Dialog#getDialogBoundsSettings()
      *
      * @since 3.2
      */
     protected IDialogSettings getDialogBoundsSettings() {
         IDialogSettings settings = CheatSheetPlugin.getPlugin().getDialogSettings();
         IDialogSettings section = settings.getSection(DIALOG_SETTINGS_SECTION);
         if (section == null) {
             section = settings.addNewSection(DIALOG_SETTINGS_SECTION);
         }
         return section;
     }
     
     private Label createMessageArea(Composite composite) {
         Label label = new Label(composite, SWT.NONE);
         label.setText(Messages.CHEAT_SHEET_SELECTION_DIALOG_MSG);
         label.setFont(composite.getFont());
         return label;
     }

     public IStatus getStatus() {
         return status ;
     }
 }

